using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using Newtonsoft.Json;
using System.IO;

public class GlobalKeyboardListener : MonoSingleton<GlobalKeyboardListener>
{
    private const string KEY_PRESS_DATA_FILE_NAME = "key_press_data.json";
    private Dictionary<Keys, bool> _keysPressing = new Dictionary<Keys, bool>();
    public Dictionary<Keys, float> keysPressTime = new Dictionary<Keys, float>();
    public Dictionary<Keys, int> keysPressCount = new Dictionary<Keys, int>();
    public Dictionary<Keys, int> keysPressCountSinceStartup = new Dictionary<Keys, int>();
    public int totalClickCount = 0;
    public int clickCountSinceStartup = 0;
    private List<Action<Keys>> keyDownHandlers = new List<Action<Keys>>();
    private float _timer = 0;

    protected override void AutoInit()
    {
        var path = Path.Combine(Application.persistentDataPath, KEY_PRESS_DATA_FILE_NAME);
        if (File.Exists(path))
        {
            var jsonStr = File.ReadAllText(path);
            var keyPressData = JsonConvert.DeserializeObject<KeyPressData>(jsonStr);
            keysPressTime = keyPressData.keysPressTime;
            keysPressCount = keyPressData.keysPressCount;
            foreach (var kv in keysPressCount)
            {
                totalClickCount += kv.Value;
            }
        }
    }

    void Update()
    {
        Array keyValues = Enum.GetValues(typeof(Keys));
        foreach (Keys key in keyValues)
        {
            if ((GetAsyncKeyState((int)key) & 0x8000) != 0)
            {
                if (!_keysPressing.ContainsKey(key))
                {
                    // 按键按下
                    _keysPressing[key] = true;

                    // Debug.Log("key pressed: " + key.ToString());

                    totalClickCount++;
                    clickCountSinceStartup++;
                    if (!keysPressCount.ContainsKey(key))
                        keysPressCount[key] = 1;
                    else
                        keysPressCount[key]++;

                    if (!keysPressCountSinceStartup.ContainsKey(key))
                        keysPressCountSinceStartup[key] = 1;
                    else
                        keysPressCountSinceStartup[key]++;

                    foreach (var handler in keyDownHandlers)
                    {
                        handler(key);
                    }
                }
                if (!keysPressTime.ContainsKey(key))
                {
                    keysPressTime[key] = Time.deltaTime;
                }
                else
                {
                    keysPressTime[key] += Time.deltaTime;
                }
            }
            else
            {
                if (_keysPressing.ContainsKey(key)) {
                    _keysPressing.Remove(key);
                }
            }
        }

        _timer += Time.deltaTime;
        if (_timer > 60)
        {
            _timer = 0;
            Save();
        }
    }

    // 将keysPressCount 和 keysPressTime 保存到本地json文件

    private void Save(){
        var data = new KeyPressData
        {
            keysPressTime = keysPressTime,
            keysPressCount = keysPressCount,
        };
        var jsonStr = JsonConvert.SerializeObject(data);
        string path = Path.Combine(Application.persistentDataPath, KEY_PRESS_DATA_FILE_NAME);
        File.WriteAllText(path, jsonStr);
    }
    void OnApplicationQuit()
    {
        Save();
    }

    public void AddKeyDownHandler(Action<Keys> handler){
        keyDownHandlers.Add(handler);
    }

    public void RemoveKeyDownHandler(Action<Keys> handler){
        keyDownHandlers.Remove(handler);
    }

    [DllImport("user32.dll")]
    private static extern short GetAsyncKeyState(int vKey);

}

[System.Serializable]
public class KeyPressData
{
    public Dictionary<Keys, float> keysPressTime;
    public Dictionary<Keys, int> keysPressCount;
}

[Serializable]
public enum Keys
{
    LeftMouseBtn = 1,
    RightMouseBtn = 2,
    CtrlBrkPrcs = 3,
    MidMouseBtn = 4,
    ThumbForward = 5,
    ThumbBack = 6,
    BackSpace = 8,
    Tab = 9,
    Clear = 12,
    Enter = 13,
    Pause = 19,
    CapsLock = 20,
    Kana = 21,
    Junju = 23,
    Final = 24,
    Hanja = 25,
    Escape = 27,
    Convert = 28,
    NonConvert = 29,
    Accept = 30,
    ModeChange = 31,
    Space = 32,
    PageUp = 33,
    PageDown = 34,
    End = 35,
    Home = 36,
    LeftArrow = 37,
    UpArrow = 38,
    RightArrow = 39,
    DownArrow = 40,
    Select = 41,
    Execute = 43,
    PrintScreen = 44,
    Insert = 45,
    Delete = 46,
    Help = 47,
    Num0 = 48,
    Num1 = 49,
    Num2 = 50,
    Num3 = 51,
    Num4 = 52,
    Num5 = 53,
    Num6 = 54,
    Num7 = 55,
    Num8 = 56,
    Num9 = 57,
    A = 65,
    B = 66,
    C = 67,
    D = 68,
    E = 69,
    F = 70,
    G = 71,
    H = 72,
    I = 73,
    J = 74,
    K = 75,
    L = 76,
    M = 77,
    N = 78,
    O = 79,
    P = 80,
    Q = 81,
    R = 82,
    S = 83,
    T = 84,
    U = 85,
    V = 86,
    W = 87,
    X = 88,
    Y = 89,
    Z = 90,
    LeftWin = 91,
    RightWin = 92,
    Apps = 93,
    Sleep = 95,
    Numpad0 = 96,
    Numpad1 = 97,
    Numpad2 = 98,
    Numpad3 = 99,
    Numpad4 = 100,
    Numpad5 = 101,
    Numpad6 = 102,
    Numpad7 = 103,
    Numpad8 = 104,
    Numpad9 = 105,
    Multiply = 106,
    Add = 107,
    Separator = 108,
    Subtract = 109,
    Decimal = 110,
    Divide = 111,
    F1 = 112,
    F2 = 113,
    F3 = 114,
    F4 = 115,
    F5 = 116,
    F6 = 117,
    F7 = 118,
    F8 = 119,
    F9 = 120,
    F10 = 121,
    F11 = 122,
    F12 = 123,
    F13 = 124,
    F14 = 125,
    F15 = 126,
    F16 = 127,
    F17 = 128,
    F18 = 129,
    F19 = 130,
    F20 = 131,
    F21 = 132,
    F22 = 133,
    F23 = 134,
    F24 = 135,
    NavigationView = 136,
    NavigationMenu = 137,
    NavigationUp = 138,
    NavigationDown = 139,
    NavigationLeft = 140,
    NavigationRight = 141,
    NavigationAccept = 142,
    NavigationCancel = 143,
    NumLock = 144,
    ScrollLock = 145,
    NumpadEqual = 146,
    FJ_Jisho = 146,
    FJ_Masshou = 147,
    FJ_Touroku = 148,
    FJ_Loya = 149,
    FJ_Roya = 150,
    LeftShift = 160,
    RightShift = 161,
    LeftCtrl = 162,
    RightCtrl = 163,
    LeftMenu = 164,
    RightMenu = 165,
    BrowserBack = 166,
    BrowserForward = 167,
    BrowserRefresh = 168,
    BrowserStop = 169,
    BrowserSearch = 170,
    BrowserFavorites = 171,
    BrowserHome = 172,
    VolumeMute = 173,
    VolumeDown = 174,
    VolumeUp = 175,
    NextTrack = 176,
    PrevTrack = 177,
    Stop = 178,
    PlayPause = 179,
    Mail = 180,
    MediaSelect = 181,
    App1 = 182,
    App2 = 183,
    OEM1 = 186,
    Plus = 187,
    Comma = 188,
    Minus = 189,
    Period = 190,
    OEM2 = 191,
    OEM3 = 192,
    Gamepad_A = 195,
    Gamepad_B = 196,
    Gamepad_X = 197,
    Gamepad_Y = 198,
    GamepadRightBumper = 199,
    GamepadLeftBumper = 200,
    GamepadLeftTrigger = 201,
    GamepadRightTrigger = 202,
    GamepadDPadUp = 203,
    GamepadDPadDown = 204,
    GamepadDPadLeft = 205,
    GamepadDPadRight = 206,
    GamepadMenu = 207,
    GamepadView = 208,
    GamepadLeftStickBtn = 209,
    GamepadRightStickBtn = 210,
    GamepadLeftStickUp = 211,
    GamepadLeftStickDown = 212,
    GamepadLeftStickRight = 213,
    GamepadLeftStickLeft = 214,
    GamepadRightStickUp = 215,
    GamepadRightStickDown = 216,
    GamepadRightStickRight = 217,
    GamepadRightStickLeft = 218,
    OEM4 = 219,
    OEM5 = 220,
    OEM6 = 221,
    OEM7 = 222,
    OEM8 = 223,
    OEMAX = 225,
    OEM102 = 226,
    ICOHelp = 227,
    ICO00 = 228,
    ProcessKey = 229,
    OEMCLEAR = 230,
    Packet = 231,
    OEMReset = 233,
    OEMJump = 234,
    OEMPA1 = 235,
    OEMPA2 = 236,
    OEMPA3 = 237,
    OEMWSCtrl = 238,
    OEMCusel = 239,
    OEMAttn = 240,
    OEMFinish = 241,
    OEMCopy = 242,
    OEMAuto = 243,
    OEMEnlw = 244,
    OEMBackTab = 245,
    Attn = 246,
    CrSel = 247,
    ExSel = 248,
    EraseEOF = 249,
    Play = 250,
    Zoom = 251,
    NoName = 252,
    PA1 = 253,
    OEMClear = 254
}